#pragma once
#include <string>
#include <GL/glew.h>

#include <utility>
/*
	The code below is somewhat based on https://github.com/heisters/ofxShader
*/
class Shader
{
public:
	Shader(std::string const & vertex_file_path, std::string const & geometry_file_path, std::string const & fragment_file_path);
	Shader(std::string const & vertex_file_path, std::string const & tessCtrl_file_path, std::string const & tessEval_file_path, std::string const & geometry_file_path, std::string const & fragment_file_path);
	

	GLuint compileShader(std::string const & filename, GLenum shaderType);
	~Shader(void);

	void begin();
	void end();

	// set matrices

	void setUniformMatrix4v(const char* name, float* v, int count = 1, bool transpose = false);

	// set a single uniform vector
	void setUniform(const char* name, int v1);
	void setUniform(const char* name, int v1, int v2);
	void setUniform(const char* name, int v1, int v2, int v3);
	void setUniform(const char* name, int v1, int v2, int v3, int v4);
	void setUniform(const char* name, float v1);
	void setUniform(const char* name, float v1, float v2);
	void setUniform(const char* name, float v1, float v2, float v3);
	void setUniform(const char* name, float v1, float v2, float v3, float v4);
	// set an array of uniform vectors
	void setUniform1v(const char* name, int* v, int count = 1);
	void setUniform2v(const char* name, int* v, int count = 1);
	void setUniform3v(const char* name, int* v, int count = 1);
	void setUniform4v(const char* name, int* v, int count = 1);
	void setUniform1v(const char* name, float* v, int count = 1);
	void setUniform2v(const char* name, float* v, int count = 1);
	void setUniform3v(const char* name, float* v, int count = 1);
	void setUniform4v(const char* name, float* v, int count = 1);
	// set attributes that vary per vertex
	void setAttribute(const char* name, short v1);
	void setAttribute(const char* name, short v1, short v2);
	void setAttribute(const char* name, short v1, short v2, short v3);
	void setAttribute(const char* name, short v1, short v2, short v3, short v4);
	void setAttribute(const char* name, float v1);
	void setAttribute(const char* name, float v1, float v2);
	void setAttribute(const char* name, float v1, float v2, float v3);
	void setAttribute(const char* name, float v1, float v2, float v3, float v4);
	void setAttribute(const char* name, double v1);
	void setAttribute(const char* name, double v1, double v2);
	void setAttribute(const char* name, double v1, double v2, double v3);
	void setAttribute(const char* name, double v1, double v2, double v3, double v4);
	void setAttributeLocation(const char* name, int index);
	int getAttributeLocation(const char* name);



	GLint getLoc(const char* name);
	GLuint programId_;



};

